﻿using System;
using System.Collections.Generic;
using FarseerPhysics.Dynamics;
using FarseerPhysics.SamplesFramework;
using Flatland.FarseerSamples.ScreenSystem;
using Flatland.Utilities;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

/**
* 
* Copyright (c) 2012 Anders Høst Kjærgaard | ahkj@itu.dk
* 
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction, 
* including without limitation the rights to use, copy, modify, merge, publish, distribute, 
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial 
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

namespace Flatland.Input {
    /// <summary>
    /// Handles input commands from the keyboard. Mostly for navigation around Flatland
    /// </summary>
    class InputHandler {
        private static int keyWait;
        private static Keys prevKey;
        /// <summary>
        /// Translates a KeyboardState to a Camera action
        /// </summary>
        /// <param name="state"></param>
        /// <param name="camera"></param>
        public static void HandleKeyboard() {
            if (0 < keyWait)
                keyWait--;
            Camera2D camera = Program.FlatlandWorld.Camera;
            KeyboardState state = Keyboard.GetState();
            if (state.IsKeyUp(prevKey))
                prevKey = Keys.None;
            foreach (var pressedKey in state.GetPressedKeys()) {
                prevKey = pressedKey;
                switch (pressedKey) {
                    case Keys.Z://in                        
                        camera.Zoom += FlatlandWorld.CAMERA_ZOOM_SCALE;
                        break;
                    case Keys.X://out
                        if (pressedKey == prevKey && 15 < keyWait) {
                            return;
                        }
                        keyWait = 17;
                        camera.Zoom -= FlatlandWorld.CAMERA_ZOOM_SCALE;
                        break;
                    case Keys.Down:
                        camera.MoveCamera(new Vector2(0, FlatlandWorld.CAMERA_PAN_SPEED));
                        break;
                    case Keys.Up:
                        camera.MoveCamera(new Vector2(0, -FlatlandWorld.CAMERA_PAN_SPEED));
                        break;
                    case Keys.Left:
                        camera.MoveCamera(new Vector2(-FlatlandWorld.CAMERA_PAN_SPEED, 0));
                        break;
                    case Keys.Right:
                        camera.MoveCamera(new Vector2(FlatlandWorld.CAMERA_PAN_SPEED, 0));
                        break;
                    //Print visible agent
                    case Keys.P:
                        //Program.FlatlandWorld.PrintAgents();
                        break;
                    //Breed
                    case Keys.B:
                        if (pressedKey == prevKey && keyWait != 0) {
                            return;
                        }
                        keyWait = 17;
                        Program.FlatlandWorld.BreedAgent();
                        break;
                    case Keys.C:
                        if (pressedKey == prevKey && keyWait != 0) {
                            return;
                        }
                        keyWait = 17;
                        Program.FlatlandWorld.ChangeBackgroundColor();
                        break;
                    //Feed
                    case Keys.F:
                        if (pressedKey == prevKey && keyWait != 0) {
                            return;
                        }
                        keyWait = 17;
                        Program.FlatlandWorld.Feed(Utils.Random.Next(100));
                        break;
                        break;
                    case Keys.I:
                        Console.WriteLine("Agent 0 pos: " + ((Agent)Program.FlatlandWorld.Flatlanders[0]).Body.Position);
                        break;
                    case Keys.G:
                        if (pressedKey == prevKey && keyWait != 0) {
                            return;
                        }
                        keyWait = 17;
                        Program.FlatlandWorld.PrintAgent();
                        break;
                    /*
                     * Show info panel
                     */
                    case Keys.H:
                        if (pressedKey == prevKey && keyWait != 0) {
                            return;
                        }
                        keyWait = 17;
                        Program.FlatlandWorld.ShowInfoPanel();
                        break;
                    //Quit
                    case Keys.Q:
                        Program.FlatlandWorld.Exit();
                        break;


                    //case Keys.D1:
                    //    Program.FlatlandWorld.SimulationSpeed = 10 - 1;
                    //    break;
                    //case Keys.D2:
                    //    Program.FlatlandWorld.SimulationSpeed = 10 - 2;
                    //    break;
                    //case Keys.D3:
                    //    Program.FlatlandWorld.SimulationSpeed = 10 - 3;
                    //    break;
                    //case Keys.D4:
                    //    Program.FlatlandWorld.SimulationSpeed = 10 - 4;
                    //    break;
                    //case Keys.D5:
                    //    Program.FlatlandWorld.SimulationSpeed = 10 - 5;
                    //    break;
                    //case Keys.D6:
                    //    Program.FlatlandWorld.SimulationSpeed = 10 - 6;
                    //    break;
                    //case Keys.D7:
                    //    Program.FlatlandWorld.SimulationSpeed = 10 - 7;
                    //    break;
                    //case Keys.D8:
                    //    Program.FlatlandWorld.SimulationSpeed = 10 - 8;
                    //    break;
                    //case Keys.D9:
                    //    Program.FlatlandWorld.SimulationSpeed = 10 - 9;
                    //    break;
                }
            }
        }

        private static bool _leftDown;
        private static Fixture _followed = null;
        /// <summary>
        /// Handles mouse input.
        /// Left clicks are tested for a small area around the pixel being clicked which especially makes
        /// it easier to click on women shapes.
        /// </summary>
        public static void HandleMouse() {
            if (Mouse.GetState().LeftButton == ButtonState.Released) {
                _leftDown = false;
            }
            if (Mouse.GetState().LeftButton == ButtonState.Pressed) {
                float w = Program.FlatlandWorld.GraphicsDeviceManager.PreferredBackBufferWidth / 2;
                float h = Program.FlatlandWorld.GraphicsDeviceManager.PreferredBackBufferHeight / 2;
                //Console.WriteLine("x,y " + Program.FlatlandWorld.Camera.ConvertScreenToWorld(new Vector2(Mouse.GetState().X, Mouse.GetState().Y))); 
                if (_leftDown)
                    return;
                _leftDown = true;
                int radius = 3;
                int x = Mouse.GetState().X;
                int y = Mouse.GetState().Y;
                for (int i = x -radius; i < x + radius; i++) {
                    for (int j = y - radius; j < y + radius; j++) {
                        List<Fixture> fixtures = Program.FlatlandWorld.World.TestPointAll(Program.FlatlandWorld.Camera.ConvertScreenToWorld(new Vector2(i, j)));
                        foreach (var fixture in fixtures) {
                            if (fixture.CollisionCategories == Category.Agent) {
                                Program.FlatlandWorld.Follow(fixture.Body);
                                return;
                            }
                        }
                    }
                }

                Program.FlatlandWorld.Unfollow();
            }
        }
    }
}
